#include "unique_random_branching.h"

UniqueRandomBranching::UniqueRandomBranching(Space *s, ViewArray<IntView> &x):
  Branching(s), x(x) {
}

UniqueRandomBranching::UniqueRandomBranching(Space *s,
                                             bool share,
                                             UniqueRandomBranching &b):
                                             Branching(s,share,b) {
  x.update(s,share,b.x);
}

Actor * UniqueRandomBranching::copy(Space *s, bool share) {
  return new (s) UniqueRandomBranching(s, share , *this);
}

bool UniqueRandomBranching::status(const Space*) const {
  for (int pos = 0; pos < x.size(); pos++)
    if (!x[pos].assigned())
      return true;

  return false;
}

const BranchingDesc * UniqueRandomBranching::description(const Space*) const {
  for (int pos = 0; pos < x.size(); pos++) {
    // pour une valeur non assignée du domaine
    // on choisit une valeur possible de façon aléatoire
    if (!x[pos].assigned()) {
      IntView iv(x[pos]);

      int size = (int) ((float) rand() / RAND_MAX * (iv.size() + 1));

      ViewValues<IntView> vv(iv);
      for(int j=0; j<size; j++)
        ++vv;

      return new PosValDesc<int,2>(this,pos,vv.val());
    }
  }

  return 0;
}

ExecStatus UniqueRandomBranching::commit(Space *s, const BranchingDesc *d,
                                         unsigned int a) {
  const PosValDesc<int,2>* pvd = static_cast<const PosValDesc<int,2>*>(d);

  if(a)
    return me_failed(x[pvd->pos()].eq(s, pvd->val())) ? ES_FAILED : ES_OK;
  else
    return me_failed(x[pvd->pos()].nq(s, pvd->val())) ? ES_FAILED : ES_OK;
}

void UniqueRandomBranching::post(Space *s, IntVarArgs x) {
  ViewArray<Int::IntView> xv(s, x);
  new (s) UniqueRandomBranching(s, xv);
}
